#ifndef RSIM_REPORTER_H
#define RSIM_REPORTER_H

/* -------------------------------------------------------------------------- *
 * File: Reporter.h                                                           *
 * Authors: Kishor Bhalerao                                                   *
 * Email : kishor8dm@gmail.com                                                *
 * Contributors:                                                              *
 * Email:                                                                     *
 * copyright (c) 2010 Authors.                                                *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify it    *
 * under the terms of the GNU General Public License as published by the Free *
 * Software Foundation, either version 3 of the License, or any later version.*
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details. (http://www.gnu.org/licenses/)                           *
 * -------------------------------------------------------------------------- */

#include "FileIO.h"

#include <fstream>

namespace RSIM{

class MultibodySystem;
class State;

/** 
This class can be used to obtain custom data from the integrator. A user defined class can be added
to an object of the class Integrator using the function Integrator::addReporter(). 
*/
class Reporter{
        public:
                /** 
                Reporter cannot modify the system or the state. 
                @param report_interval is the interval at which custom data is to be obtained during integration.
                */
                Reporter(const MultibodySystem& MBS, 
                        const State& state, 
                        const double& report_interval):
                        sys_(MBS),state_(state),ReportInterval_(report_interval){}
                
                /** This function is called every ReportInterval_ time by the integrator.*/
                virtual void report()=0;
                
                const double& getReportInterval()const{
                        return ReportInterval_;
                }
                
        protected:
                const MultibodySystem& sys_;
                const State& state_;
                const double& ReportInterval_;
        private:
                Reporter(const Reporter&);
                
}; // class Reporter

/** This writes the state vector of the system [q,u]' every report_interval */
class StateReporter:public Reporter{
        public:
                /** 
                @param report_interval is the time interval at which the function Reporter::report() is called by the integrator
                @param opfile is the file in which the state vector of the system is written every report_interval */
                StateReporter(const MultibodySystem& sys, 
                        const State& state,
                        const double& report_interval,
                        fstream& opfile):
                        Reporter(sys,state,report_interval), OpFile_(opfile){}
                
                void report(){
                        FileIO::appendStateVectorToFile(state_, OpFile_);
                }
                
        private:
                fstream& OpFile_;
};

}// namespace RSIM

#endif